﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;

namespace Radiation___IM
{
    public class CommandManager
    {
        private static CommandManager m_instance;

        public static void Init()
        {
            m_instance = new CommandManager();
            m_instance.InitCommands();
        }

        public static CommandManager Instance
        {
            get
            {
                return m_instance;
            }
        }

        // Dynamic part

        private Hashtable m_commands;
        private Hashtable m_api_commands;

        public CommandManager()
        {
            m_commands = new Hashtable();
            m_api_commands = new Hashtable();
        }

        private Type[] GetTypesInNamespace(Assembly assembly, string nameSpace)
        {
            return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray();
        }

        public void InitCommands()
        {
            Type[] typelist = GetTypesInNamespace(Assembly.GetExecutingAssembly(), "Radiation___IM.Commands");

            for (int i = 0; i < typelist.Length; i++)
            {
                ICommand command = (ICommand)Assembly.GetExecutingAssembly().CreateInstance(typelist[i].FullName);
                m_commands.Add(command.commandKey(), command);
            }

            typelist = GetTypesInNamespace(Assembly.GetExecutingAssembly(), "Radiation___IM.ApiCommands");

            for (int i = 0; i < typelist.Length; i++)
            {
                ICommand command = (ICommand)Assembly.GetExecutingAssembly().CreateInstance(typelist[i].FullName);
                m_api_commands.Add(command.commandKey(), command);
            }
        }

        public rvalue ExecuteCommand(string[] command_parts, Client client, string channel)
        {
            if (m_commands.ContainsKey(command_parts[0]))
            {
                string command = command_parts[0];
                command_parts[0] = channel;
                ((ICommand)m_commands[command]).execute(command_parts, client);
                return rvalue.COMMAND_EXECUTED;
            }

            return rvalue.COMMAND_NOT_FOUND;
        }

        public rvalue ExecuteAPICommand(string[] command_parts, Client client)
        {
            if (m_api_commands.ContainsKey(command_parts[1]))
            {
                if (isAllowedTo(client.Nickname, ((ICommand)m_api_commands[command_parts[1]]).requiredPermission()))
                    ((ICommand)m_api_commands[command_parts[1]]).execute(command_parts, client);
                else
                    MessageExecution.sendDataAPI(client, Radiation.Common.Communication.Constants.NOT_ALLOWED, command_parts[1]);

                return rvalue.COMMAND_EXECUTED;
            }

            return rvalue.COMMAND_NOT_FOUND;
        }

        private bool isAllowedTo(string nickname, string permission)
        {
            if (permission != null)
            {
                if (Users.UserManager.Instance[nickname] != null)
                {
                    return Users.UserManager.Instance[nickname].isAllowedTo(permission);
                }
                else
                    return Users.PermissionGroupManager.Instance["guest"][permission];
            }
            else
                return true;
        }
    }
}
